package cn.jingsheng.backup.servlet;

import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;

import cn.jingsheng.backup.bean.BackupFile;
import cn.jingsheng.backup.bean.PagedListInfo;
import cn.jingsheng.backup.bean.UserLogin;
import cn.jingsheng.backup.dao.BackupFileDao;
import cn.jingsheng.backup.dao.UserLoginDao;
import cn.jingsheng.backup.util.CommonUtil;
import cn.jingsheng.backup.util.DateTimeUtil;
import cn.jingsheng.backup.util.GenerateID;
import cn.jingsheng.backup.util.StringUtil;

public class BackupServlet extends HttpServlet {
	/**
	 * 序列化标志
	 */
	private static final long serialVersionUID = -4488250137069417297L;
	// BackupFile 数据库操作类
	BackupFileDao backupFileDao = new BackupFileDao();
	UserLoginDao userLoginDao = new UserLoginDao();

	/**
	 * GET 请求
	 */
	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		this.doPost(req, resp);
	}

	/**
	 * POST 请求
	 */
	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		try {
			// 设置字符编码
			req.setCharacterEncoding("UTF-8");
			resp.setCharacterEncoding("UTF-8");
			// 设置分页信息
			processPagedListInfo(req, resp);
			// 检查权限是否更新
			CommonUtil.referRoleId((UserLogin) req.getSession().getAttribute("userLogin"));
			// 逻辑分类
			String cmd = req.getParameter("cmd");
			/** 页面显示 */
			if (cmd == null || cmd.equals("show")) {
				showPage(req, resp);
			} else
			/** 文件上传 */
			if (cmd.equals("upload")) {
				upload(req, resp);
			} else
			/** 文件下载 */
			if (cmd.equals("download")) {
				download(req, resp);
			} else
			/** 报备删除 */
			if (cmd.equals("delete")) {
				remove(req, resp);
			} else
			/** 用户登录 */
			if (cmd.equals("login")) {
				login(req, resp);
			} else
			/** 用户注销 */
			if (cmd.equals("logout")) {
				logout(req, resp);
			} else
			/** 文件查看 */
			if (cmd.equals("viewinbrowse")) {
				viewInBrowse(req, resp);
			} else
			/** 状态修改 */
			if (cmd.equals("edit")) {
				editableSatus(req, resp);
			} else
			/** 显示更新页面 */
			if (cmd.equals("toupdate")) {
				toUpdate(req, resp);
			} else
			/** 更新 */
			if (cmd.equals("update")) {
				update(req, resp);
			} else
			/** 修改密码 */
			if (cmd.equals("changepwd")) {
				changePassword(req, resp);
			} else
			/** 用户列表 */
			if (cmd.equals("listUser")) {
				listUser(req, resp);
			} else
			/** 删除用户 */
			if (cmd.equals("deleteuser")) {
				deleteUser(req, resp);
			} else
			/** 批量更改用户权限 */
			if (cmd.equals("changerole")) {
				changeRole(req, resp);
			} else
			/** 新增用户 */
			if (cmd.equals("adduser")) {
				addUser(req, resp);
			}

		} catch (Exception e) {
			/** 系统错误显示 */
			req.setAttribute("exception", e);
			req.getRequestDispatcher("error.jsp").forward(req, resp);
		}
	}

	/**
	 * 主页面显示
	 * 
	 * @param req
	 * @param resp
	 * @throws ServletException
	 * @throws IOException
	 */
	protected void showPage(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		/** 分业信息 */
		PagedListInfo info = (PagedListInfo) req.getSession().getAttribute("PagedListInfo");
		// 单页显示行数
		String countOfPage = req.getParameter("countOfPage");
		if (countOfPage != null && countOfPage.matches("\\d+")) {
			info.setCountOfPage(Integer.valueOf(countOfPage));
		}
		// 关键字查询 默认为空
		String searchKey = req.getParameter("searchKey");
		if (searchKey == null) {
			searchKey = (String) req.getSession().getAttribute("searchKey");
		} else {
			req.getSession().setAttribute("searchKey", searchKey);
			info.setStartNum(1);
		}
		/** 根据关键字进行分页查询 */
		BackupFile backupFile = new BackupFile();
		backupFile.setSearchKey(searchKey);
		// 查询返回结果集
		List<BackupFile> listBackup = backupFileDao.queryList(backupFile, info);
		req.setAttribute("listBackup", listBackup);
		// 跳至显示页面
		req.getRequestDispatcher("show_file.jsp").forward(req, resp);
	}

	/**
	 * 报备下载逻辑
	 * 
	 * @param req
	 * @param resp
	 * @throws ServletException
	 * @throws IOException
	 */
	protected void viewInBrowse(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		// 报备文件主键ID
		String id = req.getParameter("id");
		if (id.matches("\\d+")) {
			BackupFile bkfile = backupFileDao.queryById(Long.valueOf(id));
			/** 文件下载协议赋值 */
			// 设为查看
			resp.setContentType(StringUtil.checkContentType(bkfile.getAliasFileName()));
			// 下载文件相对路径
			String filedownload = "/upload/" + id + ".data";
			// 显示文件名
			String filedisplay = "inline; filename=" + URLEncoder.encode(bkfile.getAliasFileName(), "UTF-8");
			// 赋值给头
			resp.addHeader("Content-Disposition", filedisplay);
			resp.setHeader("Cache-Control", "private");
			resp.setHeader("Pragma", "");

			// 转至下载文件
			RequestDispatcher disp = req.getRequestDispatcher(filedownload);
			if (disp != null) {
				disp.forward(req, resp);
			}
			// 清空缓冲区数据
			resp.flushBuffer();
		}
	}

	/**
	 * 报备删除逻辑
	 * 
	 * @param req
	 * @param resp
	 * @throws ServletException
	 * @throws IOException
	 */
	protected void remove(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		// 报备文件主键ID
		String id = req.getParameter("id");
		if (id.matches("\\d+")) {
			BackupFile bkfile = new BackupFile();
			/** 删除数据库记录 */
			bkfile.setId(id);
			backupFileDao.delete(bkfile);

			/** 删除磁盘文件 */
			String savedir = this.getServletContext().getRealPath("/upload/");
			File saveFile = new File(savedir, bkfile.getId() + ".data");
			saveFile.delete();
		}
		// 转到显示页面
		this.showPage(req, resp);
	}

	/**
	 * 文件上传
	 * 
	 * @param request
	 * @param response
	 * @throws Exception
	 */
	@SuppressWarnings("unchecked")
	protected void upload(HttpServletRequest request, HttpServletResponse response) throws Exception {

		// 判断表单是否是Multipart类型的
		if (ServletFileUpload.isMultipartContent(request)) {
			// 创建文件处理工厂，它用于生成FileItem对象。
			DiskFileItemFactory factory = new DiskFileItemFactory();
			// 设置文件的缓存路径
			String tempdir = this.getServletContext().getRealPath("/upload/temp");
			java.io.File d = new java.io.File(tempdir);
			if (!d.exists()) {
				d.mkdirs();
			}
			// 设置最多只允许在内存中存储的数据,单位:字节
			factory.setSizeThreshold(1024 * 1024);
			// 设置一旦文件大小超过getSizeThreshold()的值时数据存放在硬盘的目录
			factory.setRepository(d);

			ServletFileUpload upload = new ServletFileUpload(factory);
			// 设置允许用户上传文件大小,单位:字节 100M
			upload.setSizeMax(1024 * 1024 * 100);
			// 上传文件,并解析出所有的表单字段，包括普通字段和文件字段
			List<FileItem> listFileItem = upload.parseRequest(request);
			// 报备文件普通字段赋值
			BackupFile bkfile = parseField(listFileItem);
			// 报备文件处理
			parseFile(bkfile, listFileItem);
		}
		response.getWriter().print("<script>window.close();</script>");
		response.flushBuffer();
	}

	/**
	 * 提取字段值
	 * 
	 * @param listFileItem
	 *            表单字段集合
	 * @return
	 * @throws UnsupportedEncodingException
	 */
	private BackupFile parseField(List<FileItem> listFileItem) throws UnsupportedEncodingException {
		BackupFile bkfile = new BackupFile();
		/** 循环处理表单字段 */
		for (int i = 0; i != listFileItem.size(); i++) {
			// 表单字段
			FileItem fileItem = listFileItem.get(i);
			if (fileItem.isFormField()) {
				// 得到字段name属性的值
				String fieldName = fileItem.getFieldName();
				// 得到该字段的值,默认的编码格式
				String fieldValue = fileItem.getString("UTF-8");
				// 公司
				if ("company".equals(fieldName)) {
					bkfile.setCompany(fieldValue);
				} else if ("createUser".equals(fieldName)) {
					bkfile.setCreateUser(fieldValue);
				} else if ("searchKey".equals(fieldName)) {
					bkfile.setSearchKey(fieldValue);
				} else if ("createUser".equals(fieldName)) {
					bkfile.setCreateUser(fieldValue);
				} else if ("id".equals(fieldName)) {
					bkfile.setId(fieldValue);
					// 删除报备文件
					backupFileDao.delete(bkfile);
					bkfile.setId(null);
				}
			}
		}
		bkfile.setCreateTime(DateTimeUtil.getCurrentTimestamp());
		return bkfile;
	}

	/**
	 * 处理上传文件
	 * 
	 * @param bkfile
	 * @param listFileItem
	 * @throws Exception
	 */
	public void parseFile(BackupFile bkfile, List<FileItem> listFileItem) throws Exception {
		for (int i = 0; i != listFileItem.size(); i++) {
			// 表单字段
			FileItem fileItem = listFileItem.get(i);
			// 文件处理逻辑
			if (!fileItem.isFormField()) {
				// 文件字段赋值
				File uploadFile = new File(fileItem.getName());
				// 主键ID
				bkfile.setId(GenerateID.createId().toString());
				// 文件名
				bkfile.setAliasFileName(uploadFile.getName());
				// 自动将文件名加入关键字
				if (null != bkfile.getSearchKey()) {
					StringBuilder sb = new StringBuilder();
					sb.append(bkfile.getSearchKey());
					String keys[] = bkfile.getAliasFileName().split("\\.");
					for (int a = 0; keys != null && a != keys.length; a++) {
						sb.append(" ");
						sb.append(keys[a]);
					}
					bkfile.setSearchKey(sb.toString());
				}

				// 设置文件的保存路径
				String savedir = this.getServletContext().getRealPath("/upload/");
				File saveFile = new File(savedir, bkfile.getId() + ".data");
				saveFile.delete();
				fileItem.write(saveFile);
				// 数据入库
				backupFileDao.insert(bkfile);
			}
		}
	}

	/**
	 * 分页信息处理
	 * 
	 * @param req
	 * @param resp
	 */
	private void processPagedListInfo(HttpServletRequest req, HttpServletResponse resp) {
		PagedListInfo info = (PagedListInfo) req.getSession().getAttribute("PagedListInfo");
		// 分页信息判断逻辑
		if (info == null) {
			info = new PagedListInfo();
			req.getSession().setAttribute("PagedListInfo", info);
		}
		// 排序字段
		String sort = req.getParameter("sort");
		// 排序方向
		String ad = req.getParameter("ad");
		// 起始行号
		String startNum = req.getParameter("startNum");
		if (startNum != null && startNum.matches("\\d+")) {
			info.setStartNum(Integer.valueOf(startNum));
		}
		// 设置排列顺序
		info.sortBy(sort, ad);
	}

	/**
	 * 校验用户
	 * 
	 * @param request
	 * @param response
	 * @throws Exception
	 */
	protected void login(HttpServletRequest request, HttpServletResponse response) throws Exception {
		String username = request.getParameter("username");
		String password = request.getParameter("password");
		// 数据库校验账户与密码
		UserLogin userLogin = userLoginDao.login(username, password);
		request.getSession().setAttribute("userLogin", userLogin);

		response.setContentType("text/html; charset=UTF-8");
		response.getWriter().print("<script>");
		if (userLogin == null) {
			response.getWriter().print("alert('登录失败');");
		} else {
			response.getWriter().print("alert('登录成功');");
		}
		// 移除权限更新状态
		CommonUtil.rolesAfterModify.remove(username);
		response.getWriter().print("window.close();");
		response.getWriter().print("</script>");
		response.flushBuffer();
	}

	/**
	 * 用户注销
	 * 
	 * @param request
	 * @param response
	 * @throws Exception
	 */
	protected void logout(HttpServletRequest request, HttpServletResponse response) throws Exception {
		request.getSession().setAttribute("userLogin", null);
		this.showPage(request, response);
	}

	/**
	 * 显示更新页面
	 * 
	 * @param request
	 * @param response
	 * @throws Exception
	 */
	protected void toUpdate(HttpServletRequest request, HttpServletResponse response) throws Exception {
		/** 根据主键ID查询报备文件信息 */
		String id = request.getParameter("id");
		BackupFile bkfile = backupFileDao.queryById(Long.valueOf(id));
		request.setAttribute("backupFile", bkfile);
		// 跳至页面
		request.getRequestDispatcher("update_backup_file.jsp").forward(request, response);
	}

	/**
	 * 更新信息
	 * 
	 * @param request
	 * @param response
	 * @throws Exception
	 */
	protected void update(HttpServletRequest request, HttpServletResponse response) throws Exception {

		// 判断表单是否是Multipart类型的
		if (ServletFileUpload.isMultipartContent(request)) {
			// 创建文件处理工厂，它用于生成FileItem对象。
			DiskFileItemFactory factory = new DiskFileItemFactory();
			// 设置文件的缓存路径
			String tempdir = this.getServletContext().getRealPath("/upload/temp");
			java.io.File d = new java.io.File(tempdir);
			if (!d.exists()) {
				d.mkdirs();
			}
			// 设置最多只允许在内存中存储的数据,单位:字节
			factory.setSizeThreshold(1024 * 1024);
			// 设置一旦文件大小超过getSizeThreshold()的值时数据存放在硬盘的目录
			factory.setRepository(d);

			ServletFileUpload upload = new ServletFileUpload(factory);
			// 设置允许用户上传文件大小,单位:字节 100M
			upload.setSizeMax(1024 * 1024 * 100);
			// 上传文件,并解析出所有的表单字段，包括普通字段和文件字段
			List<FileItem> listFileItem = upload.parseRequest(request);
			// 报备文件普通字段赋值
			BackupFile bkfile = parseField(listFileItem);
			// 报备文件处理
			parseFile(bkfile, listFileItem);
		}
		this.showPage(request, response);
	}

	/**
	 * 报备条目可编辑状态
	 * 
	 * @param request
	 * @param response
	 * @throws Exception
	 */
	protected void editableSatus(HttpServletRequest request, HttpServletResponse response) throws Exception {
		// 主键
		String id = request.getParameter("id");
		// 是否可编辑
		String editable = request.getParameter("editable");
		if (StringUtil.isNotEmpty(id) && StringUtil.isNotEmpty(editable)) {
			boolean tmpEditable = Boolean.valueOf(editable);
			BackupFile bkfile = backupFileDao.queryById(Long.valueOf(id));
			// 当前状态 与 置为状态不一致时
			if (bkfile.isEditable() != tmpEditable) {
				bkfile.setEditable(tmpEditable);
				backupFileDao.updateById(bkfile);
			}
		}
		this.showPage(request, response);
	}

	/**
	 * 文件查看
	 * 
	 * @param request
	 * @param response
	 * @throws Exception
	 */
	protected void download(HttpServletRequest request, HttpServletResponse response) throws Exception {
		// 报备文件主键ID
		String id = request.getParameter("id");
		if (id.matches("\\d+")) {
			BackupFile bkfile = backupFileDao.queryById(Long.valueOf(id));
			/** 文件下载协议赋值 */
			// 设为下载
			response.setContentType("application/x-download");
			// 下载文件相对路径
			String filedownload = "/upload/" + id + ".data";
			// 显示文件名
			String filedisplay = URLEncoder.encode(bkfile.getAliasFileName(), "UTF-8");
			// 赋值给头
			response.addHeader("Content-Disposition", "attachment;filename=" + filedisplay);
			// 转至下载文件
			RequestDispatcher disp = request.getRequestDispatcher(filedownload);
			if (disp != null) {
				disp.forward(request, response);
			}
			// 清空缓冲区数据
			response.flushBuffer();
		}
	}

	/**
	 * 修改密码
	 * 
	 * @param request
	 * @param response
	 * @throws Exception
	 */
	protected void changePassword(HttpServletRequest request, HttpServletResponse response) throws Exception {
		// 主键
		String username = request.getParameter("username");
		String password = request.getParameter("password");
		String newpassword = request.getParameter("newpassword");
		UserLogin userLogin = new UserLogin();
		userLogin.setUserName(username);
		userLogin.setPassword(password);
		int result = userLoginDao.changePassword(userLogin, newpassword);
		// 密码修改失败
		if (result == 0) {
			response.getWriter().write("<script>alert('密码修改失败!');window.close();</script>");
			response.flushBuffer();
		} else {
			// 修改成功
			response.getWriter().write("<script>alert('密码修改成功!');window.close();</script>");
		}
	}

	/**
	 * 用户列表
	 * 
	 * @param request
	 * @param response
	 * @throws Exception
	 */
	protected void listUser(HttpServletRequest request, HttpServletResponse response) throws Exception {
		// 权限校验
		if (!CommonUtil.isAdministrator(request.getSession())) {
			request.setAttribute("msg", "非法操作,此操作需管理员权限");
			request.getRequestDispatcher("alert_close.jsp").forward(request, response);
			return;
		}
		// 查询列表
		List<UserLogin> list = userLoginDao.queryAll();
		request.setAttribute("userList", list);
		request.getRequestDispatcher("list_user.jsp").forward(request, response);
	}

	/**
	 * 删除用户
	 * 
	 * @param request
	 * @param response
	 * @throws Exception
	 */
	protected void deleteUser(HttpServletRequest request, HttpServletResponse response) throws Exception {
		// 权限校验
		if (!CommonUtil.isAdministrator(request.getSession())) {
			request.setAttribute("msg", "非法操作,此操作需管理员权限");
			request.getRequestDispatcher("alert_close.jsp").forward(request, response);
			return;
		}
		/** 删除用户 */
		String username = request.getParameter("username");
		userLoginDao.deleteUserByName(username);
		/** 显示用户列表 */
//		this.listUser(request, response);
		//防刷新
		response.sendRedirect("BackupServlet?cmd=listUser");
	}
	/**
	 * 新增用户
	 * 
	 * @param request
	 * @param response
	 * @throws Exception
	 */
	protected void addUser(HttpServletRequest request, HttpServletResponse response) throws Exception {
		// 权限校验
		if (!CommonUtil.isAdministrator(request.getSession())) {
			request.setAttribute("msg", "非法操作,此操作需管理员权限");
			request.getRequestDispatcher("alert_close.jsp").forward(request, response);
			return;
		}
		/** 新增用户 */
		String username = request.getParameter("username");
		String password = request.getParameter("password");
		UserLogin user = new UserLogin();
		user.setUserName(username);
		user.setPassword(password);
		userLoginDao.insert(user);
		/** 显示用户列表 */
//		this.listUser(request, response);
		//防刷新
		response.sendRedirect("BackupServlet?cmd=listUser");
	}

	/**
	 * 批量修改用户权限
	 * 
	 * @param request
	 * @param response
	 * @throws Exception
	 */
	protected void changeRole(HttpServletRequest request, HttpServletResponse response) throws Exception {
		// 权限校验
		if (!CommonUtil.isAdministrator(request.getSession())) {
			request.setAttribute("msg", "非法操作,此操作需管理员权限");
			request.getRequestDispatcher("alert_close.jsp").forward(request, response);
			return;
		}
		// 用户名
		String usernames[] = request.getParameterValues("username");
		// 权限列表
		String roles[] = request.getParameterValues("roleId");
		if (usernames == null || roles == null || usernames.length != roles.length) {
			request.setAttribute("msg", "数据格式错误,用户个数与权限个数不一致,或用户列表为空!");
			request.getRequestDispatcher("").forward(request, response);
		} else {
			/** 数据封装 */
			List<UserLogin> users = new ArrayList<UserLogin>();
			for (int i = 0; usernames != null && i != usernames.length; i++) {
				UserLogin user = new UserLogin();
				user.setUserName(usernames[i]);
				user.setRoleId(Integer.valueOf(roles[i]));
				users.add(user);
			}
			userLoginDao.updateRoleIdByBatch(users);
			for (int i = 0; i != users.size(); i++) {
				CommonUtil.rolesAfterModify.put(users.get(i).getUserName(), users.get(i).getRoleId());
			}
		}
		/** 显示用户列表 */
//		this.listUser(request, response);
		//防刷新
		response.sendRedirect("BackupServlet?cmd=listUser");
	}

}
